package com.muyu.danmo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.muyu.common.core.constant.Constants;
import com.muyu.common.core.domain.Result;
import com.muyu.common.core.enums.OrderStatus;
import com.muyu.common.core.enums.PayStatus;
import com.muyu.danmo.mapper.DanmoOrderMapper;
import com.muyu.danmo.mapper.GoodsEvaluationInfoMapper;
import com.muyu.danmo.mapper.OrderAfterSalesInfoMapper;
import com.muyu.danmo.service.AfterSalesService;
import com.muyu.danmo.service.IDanmoOrderService;
import com.muyu.danmo.utils.JPushUtils;
import com.muyu.system.danmo.dto.RefundDTO;
import com.muyu.system.danmo.fegin.PayFeign;
import com.muyu.system.danmo.vo.RefundResultServiceVO;
import com.muyu.system.danmo.vo.RefundResultVO;
import com.muyu.system.domain.DanmoOrder;
import com.muyu.system.domain.GoodsEvaluationInfo;
import com.muyu.system.domain.OrderAfterSalesInfo;
import com.muyu.system.domain.Vo.AfterSalesDetailVO;
import com.muyu.system.domain.Vo.StoreAddressVO;
import com.muyu.system.domain.dto.*;
import com.muyu.system.domain.enums.*;
import lombok.RequiredArgsConstructor;
import org.bouncycastle.cms.PasswordRecipientId;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.Date;
import java.util.List;
import java.util.Set;

import static com.muyu.common.core.constant.CommonConstant.REFUND_MARKET_TOP;
import static com.muyu.common.core.constant.CommonConstant.REFUND_ORDER_TOP;
import static com.muyu.common.core.constant.Constants.AFTER_SALES_DELAY_REDIS_KEY;

/**
 * @author Administrator
 */
@Service
@RequiredArgsConstructor
public class AfterSalesServiceImpl implements AfterSalesService {

    private final OrderAfterSalesInfoMapper orderAfterSalesInfoMapper;

    private final DanmoOrderMapper danmoOrderMapper;

    private final GoodsEvaluationInfoMapper goodsEvaluationInfoMapper;

    private final RedisTemplate<String, Object> redisTemplate;

    private final PayFeign payFeign;

    private final IDanmoOrderService danmoOrderService;

    private final JPushUtils jpushUtils;


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void add(AfterSalesAddDTO afterSalesAddDTO) {
        List<OrderAfterSalesInfo> list = new LambdaQueryChainWrapper<>(orderAfterSalesInfoMapper)
                .eq(OrderAfterSalesInfo::getOrderId, afterSalesAddDTO.getOrderId())
                .notIn(OrderAfterSalesInfo::getAfterSalesStatus, AfterSalesStatusEnum.REFUND_SUCCESS,AfterSalesStatusEnum.REFUND_FAIL)
                .ne(OrderAfterSalesInfo::getAuditStatus, AuditStatusEnum.REJECTED)
                .list();
        if(!list.isEmpty()){
            throw new RuntimeException("售后单已存在");
        }
        OrderAfterSalesInfo orderAfterSalesInfo = new OrderAfterSalesInfo();
        BeanUtil.copyProperties(afterSalesAddDTO, orderAfterSalesInfo);
        orderAfterSalesInfo.setAfterSalesStatus(AfterSalesStatusEnum.WAIT_SHOP);
        orderAfterSalesInfoMapper.insert(orderAfterSalesInfo);
        // 修改订单状态为售后中
        if(afterSalesAddDTO.getSource().equals(OrderSourceEnum.ORDER)){
            DanmoOrder danmoOrder = danmoOrderMapper.selectById(afterSalesAddDTO.getOrderId());
            if(!danmoOrder.getStatus().equals(OrderStatus.TO_BE_EVALUATED) &&  !danmoOrder.getStatus().equals(OrderStatus.SUCCESS)
            && !danmoOrder.getStatus().equals(OrderStatus.REJECTED)){
                throw new RuntimeException("订单状态异常");
            }
            danmoOrder.setStatus(OrderStatus.AFTER_SALES);
            danmoOrderMapper.updateById(danmoOrder);
            Long sellerId = danmoOrder.getSellerId();
            Long userId = danmoOrderMapper.findStoreById(sellerId);
            jpushUtils.send(userId, JpushMessageEnum.AFTER_SALES_APPLICATION);
        }else {
            Integer status = danmoOrderMapper.findMarketOrderStatusByPayId(afterSalesAddDTO.getOrderId());
            OrderStatus orderStatus = OrderStatus.getByCode(status);
            if(!orderStatus.equals(OrderStatus.TO_BE_EVALUATED) &&  !orderStatus.equals(OrderStatus.SUCCESS) &&
                    !orderStatus.equals(OrderStatus.REJECTED)){
                throw new RuntimeException("订单状态异常");
            }
            danmoOrderMapper.updateMarketOrderById(afterSalesAddDTO.getOrderId(), OrderStatus.AFTER_SALES.getCode());
            Long sellerUserId = danmoOrderMapper.findSellerUserIdById(afterSalesAddDTO.getOrderId());
            jpushUtils.send(sellerUserId, JpushMessageEnum.PAINTING_AFTER_SALES_APPLICATION);
        }
        DateTime dateTime = DateUtil.offsetHour(new Date(), 48);
        redisTemplate.opsForZSet().add(AFTER_SALES_DELAY_REDIS_KEY, String.valueOf(orderAfterSalesInfo.getId()), dateTime.millisecond());
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void delete(AfterSalesDeleteDTO afterSalesDeleteDTO) {
        List<OrderAfterSalesInfo> list = new LambdaQueryChainWrapper<>(orderAfterSalesInfoMapper)
                .eq(OrderAfterSalesInfo::getOrderId, afterSalesDeleteDTO.getOrderId())
                .orderByDesc(OrderAfterSalesInfo::getCreateTime).list();
        if (list.isEmpty()){
            throw new RuntimeException("售后单不存在");
        }
        orderAfterSalesInfoMapper.deleteById(list.get(0).getId());

        GoodsEvaluationInfo evaluationInfo = new LambdaQueryChainWrapper<>(goodsEvaluationInfoMapper).eq(GoodsEvaluationInfo::getOrderId, afterSalesDeleteDTO.getOrderId())
                .one();
        OrderStatus status;
        if(null == evaluationInfo){
            status = OrderStatus.TO_BE_EVALUATED;
        }else {
            status = OrderStatus.SUCCESS;
        }
        if(afterSalesDeleteDTO.getSource().equals(OrderSourceEnum.ORDER)){
            DanmoOrder order = new LambdaQueryChainWrapper<>(danmoOrderMapper).eq(DanmoOrder::getId, afterSalesDeleteDTO.getOrderId()).one();
            if(!order.getStatus().equals(OrderStatus.AFTER_SALES)){
                throw new RuntimeException("订单状态异常");
            }
            order.setStatus(status);
            danmoOrderMapper.updateById(order);
        }else {
            Integer statusCode = danmoOrderMapper.findMarketOrderStatusByPayId(afterSalesDeleteDTO.getOrderId());
            OrderStatus orderStatus = OrderStatus.getByCode(statusCode);
            if(!orderStatus.equals(OrderStatus.AFTER_SALES)){
                throw new RuntimeException("订单状态异常");
            }
            danmoOrderMapper.updateMarketOrderById(afterSalesDeleteDTO.getOrderId(), status.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void afterSalesDelay() {
        long now = System.currentTimeMillis();
        Set<Object> tasks = redisTemplate.opsForZSet().rangeByScore(AFTER_SALES_DELAY_REDIS_KEY, 0, now);
        tasks.forEach(a ->{
            OrderAfterSalesInfo one = new LambdaQueryChainWrapper<>(orderAfterSalesInfoMapper).eq(OrderAfterSalesInfo::getId, a)
                    .one();
            if(one.getAfterSalesStatus().equals(AfterSalesStatusEnum.WAIT_SHOP)){
                one.setAfterSalesStatus(AfterSalesStatusEnum.WAIT_RETURN);
                one.setIsManually(false);
                orderAfterSalesInfoMapper.updateById(one);
            }
        });

    }

    @Override
    public AfterSalesDetailVO detail(AfterSalesDeleteDTO afterSalesDeleteDTO) {
        AfterSalesDetailVO afterSalesDetailVO = new AfterSalesDetailVO();
        List<OrderAfterSalesInfo> one = new LambdaQueryChainWrapper<>(orderAfterSalesInfoMapper)
                .eq(OrderAfterSalesInfo::getOrderId, afterSalesDeleteDTO.getOrderId())
                .orderByDesc(OrderAfterSalesInfo::getCreateTime)
                .list();
        BeanUtil.copyProperties(one.get(0), afterSalesDetailVO);
        StoreAddressVO storeAddress;
        if(afterSalesDeleteDTO.getSource().equals(OrderSourceEnum.ORDER)){
            storeAddress = danmoOrderMapper.findStoreAddressById(afterSalesDeleteDTO.getStoreId());
        }else {
            storeAddress = danmoOrderMapper.findUserAddressById(afterSalesDeleteDTO.getStoreId());
        }
        afterSalesDetailVO.setStoreAddress(storeAddress);
        return afterSalesDetailVO;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void courier(CourierDTO courierDTO) {
        OrderAfterSalesInfo orderAfterSalesInfo = orderAfterSalesInfoMapper.selectById(courierDTO.getAfterSalesId());
        if(null == orderAfterSalesInfo){
            throw new RuntimeException("售后单不存在");
        }
        orderAfterSalesInfo.setDeliveryCompany(courierDTO.getDeliveryCompany());
        orderAfterSalesInfo.setDeliverySn(courierDTO.getDeliverySn());
        orderAfterSalesInfo.setAfterSalesStatus(AfterSalesStatusEnum.WAIT_SHOP_RECEIVE);
        orderAfterSalesInfoMapper.updateById(orderAfterSalesInfo);

    }

    @Override
    public void receiving(SellerReceivingDTO sellerReceivingDTO) {
        OrderAfterSalesInfo orderAfterSalesInfo = orderAfterSalesInfoMapper.selectById(sellerReceivingDTO.getAfterSalesId());
        if(null == orderAfterSalesInfo){
            throw new RuntimeException("售后单不存在");
        }
        if(!orderAfterSalesInfo.getAfterSalesStatus().equals(AfterSalesStatusEnum.WAIT_SHOP_RECEIVE)){
            throw new RuntimeException("售后单状态异常");
        }
        saleRefunds(orderAfterSalesInfo);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void merchantAudit(MerchantAuditDTO merchantAuditDTO) {
        OrderAfterSalesInfo orderAfterSalesInfo = new LambdaQueryChainWrapper<>(orderAfterSalesInfoMapper)
                .eq(OrderAfterSalesInfo::getId, merchantAuditDTO.getAfterSalesId()).one();
        if(null == orderAfterSalesInfo){
            throw new RuntimeException("售后单不存在");
        }
        if(!orderAfterSalesInfo.getAfterSalesStatus().equals(AfterSalesStatusEnum.WAIT_SHOP)){
            throw new RuntimeException("售后单状态异常");
        }
        if(merchantAuditDTO.getAuditStatus().equals(AuditStatusEnum.APPROVED)){
            if(orderAfterSalesInfo.getAfterSalesType().equals(AfterSalesTypeEnum.RETURNS_AND_REFUNDS)){
                orderAfterSalesInfo.setAuditStatus(merchantAuditDTO.getAuditStatus());
                orderAfterSalesInfo.setIsManually(true);
                orderAfterSalesInfo.setAfterSalesStatus(AfterSalesStatusEnum.WAIT_RETURN);
                orderAfterSalesInfoMapper.updateById(orderAfterSalesInfo);
            }else {
                saleRefunds(orderAfterSalesInfo);
            }
            if(orderAfterSalesInfo.getSource().equals(OrderSourceEnum.ORDER)){
                jpushUtils.send(orderAfterSalesInfo.getUserId(),JpushMessageEnum.AFTER_SALES_PASSED);
            }else {
                jpushUtils.send(orderAfterSalesInfo.getUserId(),JpushMessageEnum.PAINTING_AFTER_SALES_PASSED);
            }
        }else {
            orderAfterSalesInfo.setAuditStatus(merchantAuditDTO.getAuditStatus());
            orderAfterSalesInfo.setIsManually(true);
            orderAfterSalesInfo.setReasonsRefusal(merchantAuditDTO.getReasonsRefusal());
            orderAfterSalesInfoMapper.updateById(orderAfterSalesInfo);
            if(orderAfterSalesInfo.getSource().equals(OrderSourceEnum.ORDER)){
                new LambdaUpdateChainWrapper<>(danmoOrderMapper).eq(DanmoOrder::getId, orderAfterSalesInfo.getOrderId())
                        .set(DanmoOrder::getStatus, OrderStatus.REJECTED)
                        .update();
            }else {
                danmoOrderMapper.updateMarketOrderById(orderAfterSalesInfo.getOrderId(),  OrderStatus.REJECTED.getCode());
            }
            if(orderAfterSalesInfo.getSource().equals(OrderSourceEnum.ORDER)){
                jpushUtils.send(orderAfterSalesInfo.getUserId(),JpushMessageEnum.AFTER_SALES_REJECTION);
            }else {
                jpushUtils.send(orderAfterSalesInfo.getUserId(),JpushMessageEnum.PAINTING_AFTER_SALES_REJECTION);
            }
        }


    }


    /**
     * 售后退款
     * @param orderAfterSalesInfo
     */
    private void saleRefunds(OrderAfterSalesInfo orderAfterSalesInfo){
        orderAfterSalesInfo.setAfterSalesStatus(AfterSalesStatusEnum.WAIT_REFUND);
        orderAfterSalesInfoMapper.updateById(orderAfterSalesInfo);
        // 退款
        if(orderAfterSalesInfo.getSource().equals(OrderSourceEnum.ORDER)){
            DanmoOrder danmoOrder = danmoOrderMapper.selectById(orderAfterSalesInfo.getOrderId());
            if(!danmoOrder.getStatus().equals(OrderStatus.AFTER_SALES)){
                throw new RuntimeException("订单状态异常");
            }
            danmoOrder.setRefundOrderSn(REFUND_ORDER_TOP + RandomUtil.randomNumbers(16));
            danmoOrderMapper.updateById(danmoOrder);
            // 生成退款订货单号，进行退款
            RefundDTO refundDTO = new RefundDTO();
            refundDTO.setRefundBizOrderNo(danmoOrder.getRefundOrderSn());
            refundDTO.setOrderNo(danmoOrder.getPayOrderNo());
            Result<RefundResultVO> refund = payFeign.refund(refundDTO);
            if(refund.getCode() != Constants.SUCCESS){
                throw new RuntimeException("调用支付订单退款失败");
            }
            RefundResultServiceVO refundResultServiceVO = new RefundResultServiceVO();
            refundResultServiceVO.setRefundBizOrderNo(danmoOrder.getRefundOrderSn());
            refundResultServiceVO.setStatus(refund.getData().getStatus());
            refundResultServiceVO.setCompletedTime(refund.getData().getCompletedTime());
            danmoOrderService.updateRefund(refundResultServiceVO);
        }else {
            Integer status = danmoOrderMapper.findMarketOrderStatusByPayId(orderAfterSalesInfo.getOrderId());
            OrderStatus orderStatus = OrderStatus.getByCode(status);
            if(!orderStatus.equals(OrderStatus.AFTER_SALES)){
                throw new RuntimeException("订单状态异常");
            }
            String payOrderNo = danmoOrderMapper.findMarketOrderById(orderAfterSalesInfo.getOrderId());
            String refundOrderSn = REFUND_MARKET_TOP + RandomUtil.randomNumbers(16);
            MarketOrderDTO marketOrderDTO = new MarketOrderDTO();
            marketOrderDTO.setId(orderAfterSalesInfo.getOrderId());
            marketOrderDTO.setRefundOrderSn(refundOrderSn);
            danmoOrderMapper.updateMarketOrderDTO(marketOrderDTO);
            RefundDTO refundDTO = new RefundDTO();
            refundDTO.setRefundBizOrderNo(refundOrderSn);
            refundDTO.setOrderNo(payOrderNo);
            Result<RefundResultVO> refund = payFeign.refund(refundDTO);
            if(refund.getCode() != Constants.SUCCESS){
                throw new RuntimeException("调用支付订单退款失败");
            }
            RefundResultServiceVO refundResultServiceVO = new RefundResultServiceVO();
            refundResultServiceVO.setRefundBizOrderNo(refundOrderSn);
            refundResultServiceVO.setStatus(refund.getData().getStatus());
            refundResultServiceVO.setCompletedTime(refund.getData().getCompletedTime());
            danmoOrderService.updateRefund(refundResultServiceVO);
        }
    }

}
